package cn.cloudtogo.server.redis;

import cn.cloudtogo.common.GendbException;
import cn.cloudtogo.common.model.ExternalDatasourceDao;
import cn.cloudtogo.common.model.ExternalDatasourceModel;
import cn.cloudtogo.common.types.RequestHeaderObject;
import cn.cloudtogo.support.redis.RedisConnectionHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static cn.cloudtogo.common.types.RequestHeaderObject.extractExternalDatasourceModel;

/**
 * @author yaolianhua789@gmail.com
 **/
@Component
@Slf4j
public class SpringRedisTemplateContext {

    public final Map<String, RedisTemplate<String, Object>> redisTemplateContainer = new ConcurrentHashMap<>(32);
    private final ExternalDatasourceDao externalDatasourceDao;

    public SpringRedisTemplateContext(ExternalDatasourceDao externalDatasourceDao) {
        this.externalDatasourceDao = externalDatasourceDao;
    }

    public synchronized void putRedisTemplate(RequestHeaderObject object, RedisTemplate<String, Object> redisTemplate) {
        redisTemplateContainer.put(object.getUuid(), redisTemplate);
    }

    public synchronized void remove(RequestHeaderObject requestHeaderObject) {
        redisTemplateContainer.remove(requestHeaderObject.getUuid());
    }

    public synchronized RedisTemplate<String, Object> getRedisTemplate(RequestHeaderObject o) {
        ExternalDatasourceModel model = extractExternalDatasourceModel(o);
        if (!isValid(model)) {
            throw new GendbException("key has been removed");
        }
        RedisTemplate<String, Object> redisTemplate = redisTemplateContainer.get(o.getUuid());
        //
        if (redisTemplate == null) {

            RedisConnectionHelper.ConnectionValidBind connectionValidBind = RedisConnectionHelper.isValidConnection(model.getUrl());

            if (connectionValidBind.isValid()) {
                log.info("get redisTemplate null from memory, create new one and return [{}]", model);
                RedisTemplate<String, Object> templateNew = RedisConnectionHelper.getRedisTemplate(connectionValidBind.getRedisConnectionFactory());
                this.putRedisTemplate(o, templateNew);
                return templateNew;
            }
            throw new GendbException(String.format("key is invalid [%s]", o.getUuid()));
        }

        return redisTemplate;
    }

    private boolean isValid(ExternalDatasourceModel model) {
        ExternalDatasourceModel one = externalDatasourceDao.query(model.getUuid());
        return one != null;
    }

}
